﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace CodeParser.Tokens
{
    public static class Tokenizer
    {

        public static IList<Token> GetTokens(IList<TokenParser> tokenParsers, string source)
        {
            var tokenParserArray = tokenParsers.ToArray();
            if (string.IsNullOrWhiteSpace(source)) return new List<Token>();
            var tokenParserCount = tokenParserArray.Length;
            if (tokenParserCount == 0) return new List<Token>() { new Token() { Index = 0, Type = TokenType.Unsupported, Value = source } };
            var sourceLength = source.Length;
            var tokenList = new List<Token>();
            var index = 0;
            var unsupported = new StringBuilder();
            while (index < sourceLength)
            {
                var currentChar = source[index];
                if (currentChar == ' ' || currentChar == '\t' || currentChar == '\r' || currentChar == '\n')
                {
                    index++;
                    continue;
                }
                Token token = null;
                TokenParser parser = null;
                var winI = 0;
                // find largest token at the current index
                for (var i = 0; i < tokenParserCount; i++)
                {
                    parser = tokenParserArray[i];
                    token = parser.GetTokenAt(source, index);
                    if (token != null)
                    {
                        break;
                    }
                }
                // if token found, add it
                if (token != null)
                {
                    if (unsupported.Length > 0)
                    {
                        // also add unsuported content that was collected before this token
                        tokenList.Add(new Token() { Index = index - unsupported.Length, Type = TokenType.Unsupported, Value = unsupported.ToString() });
                        unsupported = new StringBuilder();
                    }
                    if (!parser.RemoveTokens)
                    {
                        tokenList.Add(token);
                    }
                    index += token.Value.Length;
                }
                else
                {
                    unsupported.Append(source[index++]);
                }
            }
            if (unsupported.Length > 0)
            {
                tokenList.Add(new Token() { Index = index - unsupported.Length, Type = TokenType.Unsupported, Value = unsupported.ToString() });
            }
            return tokenList;
        }

    }
}
